package com.bestv.search.management.datasyn;

import com.bestv.search.common.dataSource.DataSourceKey;
import com.bestv.search.common.dataSource.DataSourceKeyUtil;
import com.bestv.search.common.model.BizType;
import com.bestv.search.common.model.InfoHeader;
import com.bestv.search.common.model.uid.UID;
import com.bestv.search.common.util.StringConst;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;

import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Michael Wang
 */

// $Id$
public class VisDbMovieSyncer extends ProgramSyncerImpl {

    final static String sDBDriver = "oracle.jdbc.driver.OracleDriver";
    final static String filterFile = "filterWords.properties";
    final static int progValid = 1;

    String orclUrl = null;
    String encoding = "ISO8859_1";
    String user = null;
    String pass = null;
    String movieView = null;

    public VisDbMovieSyncer(Map<String, String> p) throws Exception {
        this.setProps(p);
        justDoIt();
    }

    @Override
    public boolean init(Map<String, String> properties) {

        // init last sync time
        if (!initLastSyncTime(StringConst.BESTV_VIS, 1, StringConst.VIS_MOVIE_SYNC_TIME)) {
            return false;
        }

        // Gets orclUrl
        if (props.get("orclUrl") == null || props.get("orclUrl").length() == 0) {
            logger.error("orclUrl is empty!");
            result = false;
            return false;
        } else {
            orclUrl = props.get("orclUrl");
        }

        // Gets movie view
        if (props.get("movie") == null || props.get("movie").length() == 0) {
            logger.error("movie view is empty!");
            result = false;
            return false;
        } else {
            movieView = props.get("movie");
        }

        // Gets encoding
        if (props.get("encoding") == null || props.get("encoding").length() == 0) {
            logger.warn("encoding is empty, use ISO8859_1");
        } else {
            encoding = props.get("encoding");
        }

        // Gets user and password
        user = props.get("user");
        pass = props.get("pass");

        return true;
    }

    @Override
    public boolean updateProgram() throws Exception {
        logger.info("Now read from vis db movie and update to search's");
        thisSyncTime = lastSyncSuccessfullTime;

        // Gets filters words that don't want to search by search engine
        String[] filtersWords = getFilterWords();

        Connection conn = null;
        ResultSet rs = null;
        Statement stmt = null;

        String syncMessage = "Success sync movie from Vis system @ " + new Date();
        try {
            Class.forName(sDBDriver);
            conn = DriverManager.getConnection(orclUrl, user, pass);
            stmt = conn.createStatement();

            rs = stmt.executeQuery("select * from " + movieView + " where LAST_UPDATE_TIME >= to_date('"
                    + timeformat.format(lastSyncSuccessfullTime)
                    + "','YYYY-MM-DD HH24:MI:SS') order by LAST_UPDATE_TIME asc");

            logger.info("A new batch begins at movie_update_time " + timeformat.format(lastSyncSuccessfullTime));

            boolean isValid, isNew = false;
            DataSourceKey dsKey = DataSourceKeyUtil.convert(systemCache.getLocalDataSourceKey());
            while (rs.next()) {
                Date now = new Date();
                try {
                    InfoHeader header = new InfoHeader();
                    int status = rs.getInt("status");
                    isValid = status == progValid;

                    String name = unifyStr(rs.getString("name"));
                    String p_type = unifyStr(rs.getString("CONTENT_TYPE"));
                    String code = rs.getString("code");

                    Date updateTime = rs.getTimestamp("LAST_UPDATE_TIME");
                    if (thisSyncTime == null || updateTime.after(thisSyncTime)) {
                        thisSyncTime = updateTime;
                    }

                    List<InfoHeader> headers = infoHeaderManager.get(dsKey, name, p_type);

                    if (headers != null && headers.size() > 0) {
                        isNew = false;
                        for (int x = 0; x < headers.size(); x++) {
                            InfoHeader headerInDB = headers.get(x);
                            if (x == 0) {
                                header = headerInDB;
                            } else {
                                header.setStatus(0);
                                header.setUpdate_time_for_index(now);
                                header.setLast_update_time(updateTime);
                                infoHeaderManager.saveOrUpdate(dsKey, header);
                            }
                        }
                    } else {
                        InfoHeader headerInDB = infoHeaderManager.get(dsKey, code);
                        if (headerInDB == null) {
                            isNew = true;
                        } else {
                            header = headerInDB;
                        }
                    }

                    header.setStatus(isValid ? 1 : 0);
                    header.setCode(code);
                    header.setName(name);
                    header.setP_type(p_type);
                    BizType bizType = bm.getBizTypeByName(dsKey, p_type);
                    if (bizType == null) {
                        p_type = "其他";
                        bizType = bm.getBizTypeByName(dsKey, p_type);
                    }
                    header.setBizType(bizType);
                    header.setLast_update_time(updateTime);
                    header.setUpdate_time_for_index(now);

                    header.setGenre(unifyStr(rs.getString("GENRE")));
                    // Check genre whether contains word that need to be
                    // filtered
                    if (containsSubWordInArray(filtersWords, header.getGenre())) {
                        // Contains, set status = 0
                        header.setStatus(0);
                        logger.info("Genre contains word that need to be filtered, offline info by mediaCode "
                                + header.getCode());
                    }

                    // Gets Keywords
                    String kws = unifyStr(rs.getString("keywords"));
                    StringBuilder keywordSb = new StringBuilder();
                    if (kws != null && kws.trim().length() != 0) {
                        String[] keywords = kws.split("[\\[\\]\\-,;、 ]+");
                        int i = 0;
                        for (String key : keywords) {
                            i++;
                            if (key == null || "".equals(key))
                                continue;
                            keywordSb.append(key);
                            if (i < keywords.length) {
                                keywordSb.append(StringConst.SPACE);
                            }
                        }
                    }
                    header.setKeywords(keywordSb.toString());

                    // Gets tags
                    String tags = unifyStr(rs.getString("TAGS"));
                    StringBuilder tagSb = new StringBuilder();
                    if (tags != null && tags.trim().length() != 0) {
                        String[] tagsArray = tags.split("[\\[\\]\\-,;、 ]+");
                        int i = 0;
                        for (String tg : tagsArray) {
                            if (tg == null || "".equals(tg))
                                continue;
                            tagSb.append(tg);
                            if (i < tagsArray.length) {
                                tagSb.append(StringConst.SPACE);
                            }
                        }
                        // 设置节目是否收费
                        if (tagSb.toString().contains("看大片") || tagSb.toString().contains("首映"))
                            header.setIsCharge(1);
                    }
                    header.setTags(tagSb.toString());

                    String actors = unifyStr(rs.getString("ACTOR_DISPLAY"));
                    header.setActors(actors);

                    String directors = unifyStr(rs.getString("WRITER_DISPLAY"));
                    header.setWriters(directors);

                    header.setRegion(unifyStr(rs.getString("REGION")));
                    header.setReleased(yearformat.parse(String.valueOf(rs.getInt("ISSUE_YEAR"))));
                    header.setDescription(unifyStr(rs.getString("DESCRIPTION")));

                    // Gets Clarity flag 0：没有高清和标清 1：只有标清 2： 只有高清 3：有高清和标清
                    int hdsd = rs.getInt("HDSDFLAG");
                    header.setClarity_flag(hdsd);
                    header.setHeaderType(StringConst.MOVIE);

                    // Check name whether contains word that need to be
                    // filtered
                    if (containsSubWordInArray(filtersWords, name)) {
                        // Contains, set updateFlag =2
                        header.setStatus(0);
                        logger.info("Name contains word that need to be filtered " + header.getCode());
                    }
                    if (isNew) {
                        header.setId(new Long(UID.getUID(header)));
                    }

                    // Save to DB
                    infoHeaderManager.saveOrUpdate(dsKey, header);
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("read movie error! pcode=" + rs.getString("code"));
                }
            }
        } catch (Exception e) {
            System.out.println(e);
            syncMessage = "Failed sync Movie from Vis system @ " + new Date();
            result = false;
            throw e;
        } finally {
            if (rs != null)
                rs.close();
            if (stmt != null)
                stmt.close();
            if (conn != null)
                conn.close();

            // Update Sync status.
            updateSyncStatus(StringConst.BESTV_VIS, 1, StringConst.VIS_MOVIE_SYNC_TIME, syncMessage, thisSyncTime);
        }

        return true;
    }

    String unifyStr(String s) throws UnsupportedEncodingException {
        if (s == null)
            return null;
        String toCode = encoding.equalsIgnoreCase("iso-8859-1") ? "gbk" : "utf-8";
        return new String(s.getBytes(encoding), toCode).trim();
    }

    private String[] getFilterWords() {
        PropertiesConfiguration config;
        try {
            config = new PropertiesConfiguration(filterFile);
            config.setReloadingStrategy(new FileChangedReloadingStrategy());
            String filterStr = config.getString("filter");
            return filterStr.split("_");
        } catch (Exception e) {
            logger.error("Gets filter word failed " + e.getMessage());
        }

        return null;
    }

    private boolean containsSubWordInArray(String[] array, String word) {
        if (array == null || array.length == 0 || word == null) {
            return false;
        } else {
            for (String wordInArray : array) {
                if (word.contains(wordInArray)) {
                    return true;
                }
            }
        }
        return false;
    }
}
